<?php


namespace app\cms\community\lib\utils;


use app\cms\model\themeModel;
use iflow\Container\implement\annotation\tools\data\Inject;
use iflow\exception\Adapter\HttpResponseException;
use iflow\fileSystem\lib\FileList;
use iflow\fileSystem\lib\upLoadFile;
use iflow\Helper\Str\Str;
use iflow\Response;
use iflow\Utils\basicTools;

class themeUtil {

    /**
     * 上传文件列表
     * @var upLoadFile[]
     */
    protected array $files = [];

    /**
     * 临时主题保存目录
     * @var array|bool
     */
    protected array|bool $saveTempPath;

    /**
     * 主题唯一UUID
     * @var string
     */
    protected string $uuid;

    /**
     * 储存临时文件地址
     * @var string
     */
    protected string $savePath;

    /**
     * 解压文件状态
     * @var bool
     */
    protected bool $zip = false;

    /**
     * 主题配置
     * @var array|null
     */
    protected ?array $themeConfig;

    /**
     * 主题配置文件地址
     * @var string
     */
    protected string $themeJson;

    /**
     * 主题模型
     * @var themeModel
     */
    #[Inject]
    public themeModel $themeModel;

    public function __construct()
    {
        $this->uuid = Str::genUuid(true);
        $this->savePath = app() -> getRunTimePath(). 'store' . DIRECTORY_SEPARATOR . 'temp'. DIRECTORY_SEPARATOR .$this->uuid;
    }

    /**
     * 保存主题
     * @return Response
     */
    public function saveTheme(): Response
    {
        if ($this->moveUploadFileToTemp()
                -> createTheme()
                -> unZip() === false
        ) {
            $this->themeModel -> update([
                'site_theme_error' => 'unzipError',
                'status' => 2
            ], ['site_theme_uuid' => $this->uuid]);

            return message() -> update_failed('解压文件失败, 请重试');
        }

        $this->themeJson = str_replace('\\', '/', $this->savePath. "/theme.json");
        if (!file_exists($this->themeJson)) {
            return message() -> update_failed('解压文件失败, 请重试');
        }

        if (!$this->getThemeConfig()) {
            return message() -> parameter_error('配置文件 静态资源地址错误');
        }


        return $this->moveStaticResource()
            -> moveViewResource()
            -> removeTemp()
            -> themeModel
            -> updateInfo([
                'site_theme_uuid' => $this->uuid,
                'site_theme_error' => 'nil',
                'status' => 1,
                'site_theme_author' => $this -> themeConfig['author'] ?? 'nil',
                'site_theme_name' => $this -> themeConfig['themeName'] ?? 'Null',
                'site_theme_email' => $this -> themeConfig['email'] ?? 'Null',
                'site_theme_license' => $this -> themeConfig['license'] ?? 'MIT',
                'site_theme_url' => $this -> themeConfig['themeUrl'] ?? 'nil',
                'site_theme_cover' => $this -> themeConfig['cover'] ?? 'nil',
            ], [
                'site_theme_uuid' => $this->uuid
            ]);
    }

    /**
     * 获取主题配置
     * @return mixed
     */
    public function getThemeConfig(): mixed
    {
        // 进行文件格式化
        $this -> themeConfig = json_decode(
        // 获取数据后去掉BOM
            trim(file_get_contents($this->themeJson), '\xEF\xBB\xBF'), true
        );
        return $this->themeConfig;
    }

    /**
     * 新建主题
     * @return $this
     */
    protected function createTheme(): static
    {
        $save = $this->themeModel
            -> createData([
                'site_theme_error' => '等待解压中',
                'status' => 0,
                'site_theme_uuid' => $this->uuid
            ]);

        if ($save -> data['code'] !== 200) {
            throw new HttpResponseException($save);
        }
        return $this;
    }

    /**
     * 解压上传主题
     * @return bool
     */
    protected function unZip(): bool
    {
        return $this->zip = unzip($this->saveTempPath['path'], $this->savePath);
    }

    /**
     * 储存移动静态资源
     * @return $this
     */
    protected function moveStaticResource(): static
    {
        $staticList = ['js', 'css', 'images', 'other'];
        $staticRoot = app() -> getRootPath() . 'public'. DIRECTORY_SEPARATOR . 'static' . DIRECTORY_SEPARATOR . ($this->themeConfig['staticPath'] ?? $this->uuid) .DIRECTORY_SEPARATOR;
        !is_dir($staticRoot) && mkdir($staticRoot);

        array_map(function ($value) use ($staticRoot) {
            if (
                is_dir($this -> savePath . DIRECTORY_SEPARATOR . $value)
                && !file_exists($staticRoot . $value)
            ) {
                // 将资源文件移入
                rename($this -> savePath . DIRECTORY_SEPARATOR . $value, $staticRoot . $value);
            }
        }, $staticList);

        return $this;
    }

    /**
     * 存储视图文件
     * @return $this
     */
    protected function moveViewResource(): static
    {
        // 视图资源地址
        $viewFile = ['theme.json', 'html'];
        $viewRoot = config('template@view_root_path'). 'theme' . DIRECTORY_SEPARATOR . $this->uuid;
        !is_dir($viewRoot) && mkdir($viewRoot);

        array_map(function ($value) use ($viewRoot) {
            $value = trim($value, '/');
            // 将视图文件移入
            if (
                (
                    !is_dir($this->savePath . DIRECTORY_SEPARATOR . $value)
                    || file_exists($this->savePath . DIRECTORY_SEPARATOR . $value)
                ) && !file_exists($viewRoot . DIRECTORY_SEPARATOR . "${value}")
            ) {
                rename($this->savePath . DIRECTORY_SEPARATOR . $value, $viewRoot. DIRECTORY_SEPARATOR . $value);
            }
        }, $viewFile);

        return $this;
    }

    /**
     * 将文件保存至临时文件夹
     * @return $this
     */
    protected function moveUploadFileToTemp(): static
    {
        $this->saveTempPath =
            $this->files[0] -> move('runtime/store/temp', [
                'type' => 'md5',
                // 上传模板大小不能超过20M
                'size' => 1024 * 1024 * 20
            ]);
        return $this;
    }

    /**
     * 获取上传文件
     * @param array $files
     * @return $this
     */
    public function setFiles(array $files): static
    {
        $this->files = $files;
        return $this;
    }


    /**
     * 移除临时文件
     * @return $this
     */
    protected function removeTemp(): static
    {
        $fileList = new FileList();
        $fileList -> removeDir($this->savePath);
        unlink($this->saveTempPath);
        return $this;
    }

}